/**
 * YIKES this stuff is horribly redundant
 */
package
{
	import flash.events.Event;
	
	import org.flixel.*;

	public class MiniPuzzleLoader extends FlxGroup
	{ 
		// positioning constants
		private const TAB_HEIGHT:int = 30;
		private const TAB_WIDTH:int = 80;
		private const ENABLED_BG:uint = 0x091340;
		private const DISABLED_BG:uint = 0x8990D9;
			
		public static const CONTAINER_WIDTH:int = 400;
		public static const CONTAINER_HEIGHT:int = 400;
		
		private const EASY:int = 0;
		private const MEDIUM:int = 1;
		private const HARD:int = 2;
		
		// listings vectors
		private var plistings:Array;
		
		// are we displaying easy, medium or hard?
		private var currentPage:int;
		
		// thingies
		private var container:FlxSprite;
		private var body:FlxSprite;
		private var listings:FlxGroup;
		
		// footer
		private var pageNum:FlxText;
		private var prevPage:FlxText;
		private var nextPage:FlxText;
		
		// other stuffs
		private var loadingText:FlxText;
		private var loadingSprite:LoadingIndicator;
		private var emptySign:FlxText;
		private var exitButton:FlxSprite;
		
		private var loading:Boolean;
		
		private var startX:Number;
		private var startY:Number;
		
		private var friendName:String;
		private var friendID:String;
		
		private static const NUM_LISTINGS:int = 4;
		
		public function MiniPuzzleLoader(x:Number, y:Number, friendName:String, friendID:String)
		{
			super();
			this.friendName = friendName;
			this.friendID = friendID;
			startX = x;
			startY = y;
			
			initLayout();
			
			currentPage = 1;
			loading = false;
			
			requestData();
		}
		
		/**
		 * Draw the container, tabs, exit button, etc.
		 */
		public function initLayout():void {
			container = new FlxSprite();
			container.makeGraphic(CONTAINER_WIDTH, CONTAINER_HEIGHT);
			container.drawRect(0, 0, CONTAINER_WIDTH, CONTAINER_HEIGHT, 0x091340);
			container.x = startX;
			container.y = startY;
			add(container);
			
			body = new FlxSprite();
			body.makeGraphic(CONTAINER_WIDTH - 50, CONTAINER_HEIGHT-50, 0x000000, true);
			body.drawRect(0, 0, CONTAINER_WIDTH - 50, CONTAINER_HEIGHT-50, 0x444444);
			body.x = container.x + 25;
			body.y = container.y + 25;
			add(body);
			
			
			createPageFooter();
			
			listings = new FlxGroup();
			add(listings);
			
			loadingText = new FlxText(0, 0, body.width, "Loading\npuzzles\n...", false);
			loadingText.setFormat("Courier New", 24, 0xFFFFFF, "center", 1, true);
			loadingText.x = body.x + (body.width - loadingText.width)/2;
			loadingText.y = body.y + (body.height - loadingText.height)/2 - 20;
			
			loadingSprite = new LoadingIndicator(0, 0);
			loadingSprite.x = body.x + (body.width - loadingSprite.width)/2;
			loadingSprite.y = loadingText.y + loadingText.height + 10;
			
			emptySign = new FlxText(0, 0, body.width, friendName + " has not created any puzzles yet.", false);
			emptySign.setFormat("Courier New", 24, 0xFFFFFF, "center", 1, true);
			emptySign.x = body.x + (body.width - emptySign.width)/2;
			emptySign.y = body.y + (body.height - emptySign.height)/2;
			
			var title:ComponentTitle = new ComponentTitle(friendName + "'s Puzzles", container.x + (container.width-300)/2, container.y + container.width - 25);
			add(title);
		}
		
		/**
		 * If a tab is clicked, make it focused, and do another request if necessary.
		 */
		public override function update():void {
			super.update();
			
			if (FlxG.mouse.justPressed()) {
				if (prevPage.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
					requestNewPage(currentPage - 1);
				}
				
				if (nextPage.overlapsPoint(FlxG.mouse.screenX, FlxG.mouse.screenY)) {
					requestNewPage(currentPage + 1);
				}
			}
		}

		
		/**
		 * Clears all items in the container and makes a request to server.
		 * Called when a tab is clicked or when this class is initialized.
		 * Adds loading graphic, resets current page num to 1.
		 */
		private function requestData():void {	
			add(loadingText);
			add(loadingSprite);
			loading = true;
			Client.getAllPuzzlesCreatedBy(friendID, loadData);
		}
		
		/**
		 * Called when the page arrows are clicked.
		 * Precondition: we already have data for this difficulty type.
		 * Does nothing if the requested page is invalid.
		 */
		private function requestNewPage(requestedPage:int):void {
			var totalPages:int = Math.ceil(plistings.length / NUM_LISTINGS);
			if (requestedPage < 1 || requestedPage > totalPages) {
				return;
			}
			
			currentPage = requestedPage;
			listings.clear();
			remove(pageNum)
			remove(prevPage);
			remove(nextPage);
			
			updateListings(requestedPage);
		}
		
		/**
		 * Called when our client has received data from the server.
		 * Removes loading graphic, creates a listing for five puzzles.
		 */
		private function loadData(e:Event):void {
			var maps:String = e.target.data;
			trace("returned " + e.target.data);
			
			if (maps == "no maps") {
				remove(loadingText);
				remove(loadingSprite);
				loading = false;
				add(emptySign);
			} else {
				var mapArray:Array = maps.split("/");
				plistings = mapArray;
				
				loading = false;
				remove(loadingText);
				remove(loadingSprite);
				updateListings(currentPage);
			}
		}
		
		/**
		 * Grabs the listings for the requested batch, and updates the footer.
		 * Precondition: assumes data exists.
		 */
		private function updateListings(pageNum:int):void {
			var startIndex:int = (pageNum-1)*NUM_LISTINGS;
			for (var i:int = 0; i < NUM_LISTINGS; i++) {
				var xPos:int = body.x + 15;
				var yPos:int = body.y + (PuzzleListing.LISTING_HEIGHT * i) + ((i+1) * 15);
				
				if (startIndex + i >= plistings.length) {
					break;
				}
				
				var spec:String = plistings[startIndex + i];
				var specArray:Array = spec.split(":");
				
				var listing:MiniPuzzleListing = new MiniPuzzleListing(specArray[2], specArray[1], specArray[8], spec, xPos, yPos, friendName, friendID, MiniPuzzleListing.NORMAL_MODE);
				listings.add(listing);
			}
			
			var totalPages:int = Math.ceil(plistings.length / NUM_LISTINGS);
			updateFooter(pageNum, totalPages);
		}
		
		/**
		 * Initializes footer text (but not added to stage)
		 */
		private function createPageFooter():void {
			pageNum = new FlxText(0, 0, body.width, "", false);
			pageNum.setFormat("Courier New", 26, 0xFFFFFF, "center", 1, true);
			pageNum.x = body.x + (body.width - pageNum.width)/2;
			pageNum.y = body.y + body.height - 15 - pageNum.height;
			
			prevPage = new FlxText(0, 0, 50, "<<", false);
			prevPage.setFormat("Courier New", 26, 0xFFFFFF, "right", 1, true);
			prevPage.x = body.x + 10;
			prevPage.y = pageNum.y;
			
			nextPage = new FlxText(0, 0, 50, ">>", false);
			nextPage.setFormat("Courier New", 26, 0xFFFFFF, "left", 1, true);
			nextPage.x = body.x + body.width - 10 - nextPage.width;
			nextPage.y = pageNum.y;
		}
		
		/**
		 * Updates footer text depending on current page.
		 */
		private function updateFooter(currPage:int, totalPages:int):void {
			pageNum.text = currPage + "/" + totalPages;
			add(pageNum);
			
			if (currPage > 1) add(prevPage);
			if (currPage < totalPages) add(nextPage);
		}
		
		public function get x():Number {
			return startX;
		}
		
		public function get y():Number {
			return startY;
		}
	}
}